package com.emerquim.bean.model;

import java.util.HashSet;
import java.util.Set;

import javax.faces.context.FacesContext;

import org.apache.log4j.Logger;
import org.hibernate.HibernateException;

import com.emerquim.persistence.dao.PAgente;
import com.emerquim.persistence.dao.PAgenteDAO;
import com.emerquim.persistence.dao.PCatToxicologica;
import com.emerquim.persistence.dao.PCatToxicologicaDAO;
import com.emerquim.persistence.dao.PClaseOnu;
import com.emerquim.persistence.dao.PClaseOnuDAO;
import com.emerquim.persistence.dao.PEstadoFisico;
import com.emerquim.persistence.dao.PEstadoFisicoDAO;
import com.emerquim.persistence.dao.PGrupoQuimico;
import com.emerquim.persistence.dao.PGrupoQuimicoDAO;
import com.emerquim.persistence.dao.PIngActivo;
import com.emerquim.persistence.dao.PIngActivoDAO;
import com.emerquim.persistence.dao.PSubclaseOnu;
import com.emerquim.persistence.dao.PSubclaseOnuDAO;
import com.emerquim.persistence.dao.PSubclaseOnuId;
import com.emerquim.persistence.dao.PUso;
import com.emerquim.persistence.dao.PUsoDAO;
import com.icesoft.faces.context.effects.JavascriptContext;

/**
 * Clase para manejar los agentes
 * @author Felipe Criales
 */
public class Agente {

	/**
	 * Funcionalidad de log
	 */
	private static final Logger log = Logger.getLogger(Agente.class);
	
	// -------------------------------------------------
	// Atributos
	// -------------------------------------------------
	
	/**
	 * El identificador del agente
	 */
	private int idAgente;
	
	/**
	 * El nombre del producto
	 */
	private String nombreProducto;
	
	/**
	 * El identificador del agente activo
	 */
	private int idIngredienteActivo;
	
	/**
	 * El ingrediente activo del grupo
	 */
	private String ingredienteActivo;
	
	/**
	 * El identificador del grupo quimico
	 */
	private int idGrupoQuimico;
	
	/**
	 * El grupo quimico del agente
	 */
	private String grupoQuimico;
	
	/**
	 * El identificador del uso del agente
	 */
	private int idUso;
	
	/**
	 * El uso del agente
	 */
	private String uso;
	
	/**
	 * El identificador de la clase onu
	 */
	private int idClaseOnu;
	
	/**
	 * El numero de la clase onu del agente
	 */
	private String claseOnu;
	
	/**
	 * El numero onu del agente
	 */
	private int numeroOnu;
	
	/**
	 * El indentificador del estado fisico del agente
	 */
	private int idEstadoFisico;
	
	/**
	 * El estado fisico del agente
	 */
	private String estadoFisico;
	
	/**
	 * La cantidad de uso del agente
	 */
	private int cantidad;
	
	/**
	 * El identificador de la categoria toxicologica
	 */
	private int idCategoriaToxicologica;
	
	/**
	 * La categoria toxicologica del agente
	 */
	private String categoriaToxicologica;
	
	/**
	 * El identificador de la empresa que produjo el agente
	 */
	private int idEmpresa;
	
	/**
	 * El nombre de la empresa que produjo el agente
	 */
	private String nombreEmpresa;
	
	/**
	 * Si la empresa esta afiliada a RI
	 */
	private boolean empresaAfiliadaRI;
	
	/**
	 * GRE
	 */
	private String gre;
	
	/**
	 * Si esta confirmado el producto involucrado
	 */
	private boolean confirmado;
	
	/**
	 * Si el agente esta seleccionado en la lista
	 */
	private boolean seleccionado;
	
	/**
	 * El identificador de la via de ingreso
	 */
	private int idViaIngreso;
	
	/**
	 * El nombre de la via de ingreso
	 */
	private String viaIngreso;
	
	/**
	 * La viariable para guardar la hoja de seguridad del agente
	 */
	private String hojaSeguridad;
	
	/**
	 * Constructor de la clase con parametros		
	 * @param idAgente
	 * @param nombreProducto
	 * @param idIngredienteActivo
	 * @param ingredienteActivo
	 * @param idGrupoQuimico
	 * @param grupoQuimico
	 * @param idUso
	 * @param uso
	 * @param idClaseOnu
	 * @param claseOnu
	 * @param numeroOnu
	 * @param idEstadoFisico
	 * @param estadoFisico
	 * @param cantidad
	 * @param idCategoriaToxicologica
	 * @param categoriaToxicologica
	 * @param idEmpresa
	 * @param nombreEmpresa
	 * @param empresaAfiliadaRI
	 * @param gre
	 * @param confirmado
	 * @param seleccionado
	 */
	public Agente(int idAgente, String nombreProducto, int idIngredienteActivo,
			String ingredienteActivo, int idGrupoQuimico, String grupoQuimico,
			int idUso, String uso, int idClaseOnu, String claseOnu,
			int numeroOnu, int idEstadoFisico, String estadoFisico,
			int cantidad, int idCategoriaToxicologica,
			String categoriaToxicologica, int idEmpresa, String nombreEmpresa,
			boolean empresaAfiliadaRI, String gre, boolean confirmado,
			boolean seleccionado, int idViaIngreso, String viaIngreso,
			String hojaSeguridad) {
		this.idAgente = idAgente;
		this.nombreProducto = nombreProducto;
		this.idIngredienteActivo = idIngredienteActivo;
		this.ingredienteActivo = ingredienteActivo;
		this.idGrupoQuimico = idGrupoQuimico;
		this.grupoQuimico = grupoQuimico;
		this.idUso = idUso;
		this.uso = uso;
		this.idClaseOnu = idClaseOnu;
		this.claseOnu = claseOnu;
		this.numeroOnu = numeroOnu;
		this.idEstadoFisico = idEstadoFisico;
		this.estadoFisico = estadoFisico;
		this.cantidad = cantidad;
		this.idCategoriaToxicologica = idCategoriaToxicologica;
		this.categoriaToxicologica = categoriaToxicologica;
		this.idEmpresa = idEmpresa;
		this.nombreEmpresa = nombreEmpresa;
		this.empresaAfiliadaRI = empresaAfiliadaRI;
		this.gre = gre;
		this.confirmado = confirmado;
		this.seleccionado = seleccionado;
		this.idViaIngreso = idViaIngreso;
		this.viaIngreso = viaIngreso;
		this.hojaSeguridad = hojaSeguridad;
	}

	/**
	 * Constructor de la clase sin parametros
	 */
	public Agente(){
		this.inicializarDatos();
	}
	
	/**
	 * Inicializa los campos en blanco
	 */
	public void inicializarDatos(){
		this.idAgente = -1;
		this.nombreProducto = "";
		this.idIngredienteActivo = -1;
		this.ingredienteActivo = "";
		this.idGrupoQuimico = -1;
		this.grupoQuimico = "";
		this.idUso = -1;
		this.uso = "";
		this.idClaseOnu = -1;
		this.claseOnu = "";
		this.idEstadoFisico = -1;
		this.estadoFisico = "";
		this.cantidad = -1;
		this.idCategoriaToxicologica = -1;
		this.categoriaToxicologica = "";
		this.idEmpresa = -1;
		this.nombreEmpresa = "";
		this.empresaAfiliadaRI = false;
		this.gre = "";
		this.confirmado = false;
		this.seleccionado = false;
		this.idViaIngreso = -1;
		this.viaIngreso = "";
		this.hojaSeguridad = "";
	}
	
	/**
	 * Metodo para modificar un agente
	 */
	public void modificarAgente(Agente agente){
		this.idAgente = agente.getIdAgente();
		this.nombreProducto = agente.getNombreProducto();
		this.idIngredienteActivo = agente.getIdIngredienteActivo();
		this.ingredienteActivo = agente.getIngredienteActivo();
		this.idGrupoQuimico = agente.getIdGrupoQuimico();
		this.grupoQuimico = agente.getGrupoQuimico();
		this.idUso = agente.getIdUso();
		this.uso = agente.getUso();
		this.idClaseOnu = agente.getIdClaseOnu();
		this.claseOnu = agente.getClaseOnu();
		this.numeroOnu = agente.getNumeroOnu();
		this.idEstadoFisico = agente.getIdEstadoFisico();
		this.estadoFisico = agente.getEstadoFisico();
		this.cantidad = agente.getCantidad();
		this.idCategoriaToxicologica = agente.getIdCategoriaToxicologica();
		this.categoriaToxicologica = agente.getCategoriaToxicologica();
		this.idEmpresa = agente.getIdEmpresa();
		this.nombreEmpresa = agente.getNombreEmpresa();
		this.empresaAfiliadaRI = agente.isEmpresaAfiliadaRI();
		this.gre = agente.getGre();
		this.confirmado = agente.isConfirmado();
		this.seleccionado = agente.isSeleccionado();
		this.idViaIngreso = agente.getIdViaIngreso();
		this.viaIngreso = agente.getViaIngreso();
		this.hojaSeguridad = agente.getHojaSeguridad();
	}
	
	/**
	 * Metodo para guardar un agente en la base de datos
	 * @author Felipe Criales
	 */
	public void guardarAgente(){
		PAgenteDAO agenteDao = new  PAgenteDAO();
		PCatToxicologicaDAO catToxDao = new PCatToxicologicaDAO();
		PClaseOnuDAO claseOnuDao = new PClaseOnuDAO(); 
		PEstadoFisicoDAO estadoFisicoDao = new PEstadoFisicoDAO();
		PIngActivoDAO ingActivoDao = new PIngActivoDAO();
		PSubclaseOnuDAO subClaseOnuDao = new PSubclaseOnuDAO();
		PGrupoQuimicoDAO grupoQuimicoDao = new PGrupoQuimicoDAO();
		PUsoDAO usoDao = new PUsoDAO();
		try  {
			// 1. Crear o buscar todos los objetos para guardar un agente
			PAgente agenteGuardar = new PAgente();
			agenteGuardar.setAgeDesc(this.nombreProducto);

			// 1.1 Buscar el objeto de la categoria toxicologica			
			PCatToxicologica categoriaToxicolo = catToxDao.findById(this.idCategoriaToxicologica);
			agenteGuardar.setPCatToxicologica(categoriaToxicolo);
			
			// 1.2 Buscar la clase onu y adicionar una subclase			
			PClaseOnu claseOnu = claseOnuDao.findById(this.idClaseOnu);
						
			// 1.3 Crear la subclase para guardar
			PSubclaseOnu subClaseOnu = new PSubclaseOnu();
			PSubclaseOnuId pSubClaseOnuId = new PSubclaseOnuId();
			pSubClaseOnuId.setPClaseOnu(claseOnu);
			pSubClaseOnuId.generarSbonuIdIncrement(); // Metodo para generar el id incrementado para esa tabla
			subClaseOnu.setId(pSubClaseOnuId);
			subClaseOnu.setSbonuDesc(String.valueOf(this.numeroOnu));
			subClaseOnuDao.getSession().beginTransaction();
			subClaseOnuDao.save(subClaseOnu);
			subClaseOnuDao.getSession().getTransaction().commit();
						
			// 1.4 Asociar la subclaseonu con el agente
			Set<PSubclaseOnu> clasesOnu = new HashSet<PSubclaseOnu>();
			clasesOnu.add(subClaseOnu);
			claseOnu.setPSubclaseOnus(clasesOnu);
			agenteGuardar.setPSubclaseOnu(subClaseOnu);
			
			// 1.5 Buscar el estado fisico			
			PEstadoFisico estadoFisico = estadoFisicoDao.findById(this.idEstadoFisico);
			agenteGuardar.setPEstadoFisico(estadoFisico);			
			
			// 1.6 Crear el ingrediente activo
			PIngActivo ingredienteActivo = new PIngActivo();
			ingredienteActivo.setIacDesc(this.ingredienteActivo);
			ingActivoDao.getSession().beginTransaction();
			ingActivoDao.save(ingredienteActivo);
			ingActivoDao.getSession().getTransaction().commit();			
			agenteGuardar.setPIngActivo(ingredienteActivo);		
			
			// 1.7 Relacionar el grupo quimico
			PGrupoQuimico grupoQuimico = grupoQuimicoDao.findById(this.idGrupoQuimico);
			agenteGuardar.setPGrupoQuimico(grupoQuimico);
			
			// 1.8 Relacionar el uso
			PUso uso = usoDao.findById(this.idUso);
			agenteGuardar.setPUso(uso);
			
			// 1.9 Relacionar la empresa
			// TODO Relacionar la empresa
			
			// 1.10 Relacionar la hoja de seguridad
			agenteGuardar.setAgeHojaseg(this.hojaSeguridad);

			// 2. Guardar el objeto del dao en la base de datos				
			agenteDao.getSession().beginTransaction();
			agenteDao.save(agenteGuardar);
			agenteDao.getSession().getTransaction().commit();
			this.enviarMensajeUsuario("Se guardo exitosamente el agente");
		}catch  (HibernateException e) {
			agenteDao.getSession().getTransaction().rollback();
			subClaseOnuDao.getSession().getTransaction().rollback();
			this.enviarMensajeUsuario("Error al guardar un agente en la base de datos");
			log.error("Error al guardar un agente en la base de datos", e);
		}finally  {
			agenteDao.getSession().close();		
			catToxDao.getSession().close();		
			claseOnuDao.getSession().close();		 
			estadoFisicoDao.getSession().close();
			ingActivoDao.getSession().close();
			subClaseOnuDao.getSession().close();
			grupoQuimicoDao.getSession().close();
			usoDao.getSession().close();
		}
	}
	
	/**
	 * Metodo para enviar un mensaje de alerta el usuario
	 * @param mensaje
	 * @author Felipe Criales
	 */
	private void enviarMensajeUsuario(String mensaje){
		String funcion = "alert('"+mensaje+"');";
		JavascriptContext.addJavascriptCall(FacesContext
				.getCurrentInstance(), funcion);
	}
	
	/**
	 * Metodo para inicializar los datos dado un PAgente
	 * @author Felipe Criales
	 */
	public void setPAgente(PAgente agente){
		if(agente != null){
			this.idAgente = convertirLongToInt(agente.getAgeId());
			this.nombreProducto = agente.getAgeDesc();
			this.idIngredienteActivo = convertirLongToInt(agente.getPIngActivo().getIacId());
			this.ingredienteActivo = agente.getPIngActivo().getIacDesc();
			this.idGrupoQuimico = convertirLongToInt(agente.getPGrupoQuimico().getGrqId());
			this.grupoQuimico = agente.getPGrupoQuimico().getGrqDesc();
			this.idUso = convertirLongToInt(agente.getPUso().getUsoId());
			this.uso = agente.getPUso().getUsoDesc();
			// TODO de aca para abajo: Felipe Importante
			this.idClaseOnu = -1;
			this.claseOnu = "";
			this.idEstadoFisico = -1;
			this.estadoFisico = "";
			this.cantidad = -1;
			this.idCategoriaToxicologica = -1;
			this.categoriaToxicologica = "";
			this.idEmpresa = -1;
			this.nombreEmpresa = "";
			this.empresaAfiliadaRI = false;
			this.gre = "";
			this.confirmado = false;
			this.seleccionado = false;
			this.idViaIngreso = -1;
			this.viaIngreso = "";
			this.hojaSeguridad = agente.getAgeHojaseg();
		}
	}
	
	/**
	 * Convierte un numero de long a int
	 * @param numero el numero a convertir
	 * @return Se retorno el resultado
	 */
	private int convertirLongToInt(long numero){
		return Integer.parseInt(String.valueOf(numero));
	}


	/**
	 * @return the idAgente
	 */
	public int getIdAgente() {
		return idAgente;
	}

	/**
	 * @param idAgente the idAgente to set
	 */
	public void setIdAgente(int idAgente) {
		this.idAgente = idAgente;
	}

	/**
	 * @return the nombreProducto
	 */
	public String getNombreProducto() {
		return nombreProducto;
	}

	/**
	 * @param nombreProducto the nombreProducto to set
	 */
	public void setNombreProducto(String nombreProducto) {
		this.nombreProducto = nombreProducto;
	}

	/**
	 * @return the idIngredienteActivo
	 */
	public int getIdIngredienteActivo() {
		return idIngredienteActivo;
	}

	/**
	 * @param idIngredienteActivo the idIngredienteActivo to set
	 */
	public void setIdIngredienteActivo(int idIngredienteActivo) {
		this.idIngredienteActivo = idIngredienteActivo;
	}

	/**
	 * @return the ingredienteActivo
	 */
	public String getIngredienteActivo() {
		return ingredienteActivo;
	}

	/**
	 * @param ingredienteActivo the ingredienteActivo to set
	 */
	public void setIngredienteActivo(String ingredienteActivo) {
		this.ingredienteActivo = ingredienteActivo;
	}

	/**
	 * @return the idGrupoQuimico
	 */
	public int getIdGrupoQuimico() {
		return idGrupoQuimico;
	}

	/**
	 * @param idGrupoQuimico the idGrupoQuimico to set
	 */
	public void setIdGrupoQuimico(int idGrupoQuimico) {
		this.idGrupoQuimico = idGrupoQuimico;
	}

	/**
	 * @return the grupoQuimico
	 */
	public String getGrupoQuimico() {
		return grupoQuimico;
	}

	/**
	 * @param grupoQuimico the grupoQuimico to set
	 */
	public void setGrupoQuimico(String grupoQuimico) {
		this.grupoQuimico = grupoQuimico;
	}

	/**
	 * @return the idUso
	 */
	public int getIdUso() {
		return idUso;
	}

	/**
	 * @param idUso the idUso to set
	 */
	public void setIdUso(int idUso) {
		this.idUso = idUso;
	}

	/**
	 * @return the uso
	 */
	public String getUso() {
		return uso;
	}

	/**
	 * @param uso the uso to set
	 */
	public void setUso(String uso) {
		this.uso = uso;
	}

	/**
	 * @return the idClaseOnu
	 */
	public int getIdClaseOnu() {
		return idClaseOnu;
	}

	/**
	 * @param idClaseOnu the idClaseOnu to set
	 */
	public void setIdClaseOnu(int idClaseOnu) {
		this.idClaseOnu = idClaseOnu;
	}

	/**
	 * @return the claseOnu
	 */
	public String getClaseOnu() {
		return claseOnu;
	}

	/**
	 * @param claseOnu the claseOnu to set
	 */
	public void setClaseOnu(String claseOnu) {
		this.claseOnu = claseOnu;
	}

	/**
	 * @return the numeroOnu
	 */
	public int getNumeroOnu() {
		return numeroOnu;
	}

	/**
	 * @param numeroOnu the numeroOnu to set
	 */
	public void setNumeroOnu(int numeroOnu) {
		this.numeroOnu = numeroOnu;
	}

	/**
	 * @return the idEstadoFisico
	 */
	public int getIdEstadoFisico() {
		return idEstadoFisico;
	}

	/**
	 * @param idEstadoFisico the idEstadoFisico to set
	 */
	public void setIdEstadoFisico(int idEstadoFisico) {
		this.idEstadoFisico = idEstadoFisico;
	}

	/**
	 * @return the estadoFisico
	 */
	public String getEstadoFisico() {
		return estadoFisico;
	}

	/**
	 * @param estadoFisico the estadoFisico to set
	 */
	public void setEstadoFisico(String estadoFisico) {
		this.estadoFisico = estadoFisico;
	}

	/**
	 * @return the cantidad
	 */
	public int getCantidad() {
		return cantidad;
	}

	/**
	 * @param cantidad the cantidad to set
	 */
	public void setCantidad(int cantidad) {
		this.cantidad = cantidad;
	}

	/**
	 * @return the idCategoriaToxicologica
	 */
	public int getIdCategoriaToxicologica() {
		return idCategoriaToxicologica;
	}

	/**
	 * @param idCategoriaToxicologica the idCategoriaToxicologica to set
	 */
	public void setIdCategoriaToxicologica(int idCategoriaToxicologica) {
		this.idCategoriaToxicologica = idCategoriaToxicologica;
	}

	/**
	 * @return the categoriaToxicologica
	 */
	public String getCategoriaToxicologica() {
		return categoriaToxicologica;
	}

	/**
	 * @param categoriaToxicologica the categoriaToxicologica to set
	 */
	public void setCategoriaToxicologica(String categoriaToxicologica) {
		this.categoriaToxicologica = categoriaToxicologica;
	}

	/**
	 * @return the idEmpresa
	 */
	public int getIdEmpresa() {
		return idEmpresa;
	}

	/**
	 * @param idEmpresa the idEmpresa to set
	 */
	public void setIdEmpresa(int idEmpresa) {
		this.idEmpresa = idEmpresa;
	}

	/**
	 * @return the nombreEmpresa
	 */
	public String getNombreEmpresa() {
		return nombreEmpresa;
	}

	/**
	 * @param nombreEmpresa the nombreEmpresa to set
	 */
	public void setNombreEmpresa(String nombreEmpresa) {
		this.nombreEmpresa = nombreEmpresa;
	}

	/**
	 * @return the empresaAfiliadaRI
	 */
	public boolean isEmpresaAfiliadaRI() {
		return empresaAfiliadaRI;
	}

	/**
	 * @param empresaAfiliadaRI the empresaAfiliadaRI to set
	 */
	public void setEmpresaAfiliadaRI(boolean empresaAfiliadaRI) {
		this.empresaAfiliadaRI = empresaAfiliadaRI;
	}

	/**
	 * @return the gre
	 */
	public String getGre() {
		return gre;
	}

	/**
	 * @param gre the gre to set
	 */
	public void setGre(String gre) {
		this.gre = gre;
	}

	/**
	 * @return the confirmado
	 */
	public boolean isConfirmado() {
		return confirmado;
	}

	/**
	 * @param confirmado the confirmado to set
	 */
	public void setConfirmado(boolean confirmado) {
		this.confirmado = confirmado;
	}

	/**
	 * @return the seleccionado
	 */
	public boolean isSeleccionado() {
		return seleccionado;
	}

	/**
	 * @param seleccionado the seleccionado to set
	 */
	public void setSeleccionado(boolean seleccionado) {
		this.seleccionado = seleccionado;
	}

	/**
	 * @return the idViaIngreso
	 */
	public int getIdViaIngreso() {
		return idViaIngreso;
	}

	/**
	 * @param idViaIngreso the idViaIngreso to set
	 */
	public void setIdViaIngreso(int idViaIngreso) {
		this.idViaIngreso = idViaIngreso;
	}

	/**
	 * @return the viaIngreso
	 */
	public String getViaIngreso() {
		return viaIngreso;
	}

	/**
	 * @param viaIngreso the viaIngreso to set
	 */
	public void setViaIngreso(String viaIngreso) {
		this.viaIngreso = viaIngreso;
	}

	/**
	 * @return the hojaSeguridad
	 */
	public String getHojaSeguridad() {
		return hojaSeguridad;
	}

	/**
	 * @param hojaSeguridad the hojaSeguridad to set
	 */
	public void setHojaSeguridad(String hojaSeguridad) {
		this.hojaSeguridad = hojaSeguridad;
	}
}
